package cn.iocoder.yudao.module.famous.doctor.controller.app.famOcr.util;

import cn.iocoder.yudao.module.famous.doctor.controller.app.famOcr.Famenum.OcrEnum;
import com.alibaba.fastjson.JSON;
import dm.jdbc.filter.stat.json.JSONObject;
import jodd.util.StringUtil;
import okhttp3.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.famous.doctor.enums.ErrorCodeConstants.ATTENTION_NOT_EXISTS;
import static cn.iocoder.yudao.module.famous.doctor.enums.ErrorCodeConstants.OCR_FILS_IS_NOT_EXISTS;

/**
 * @author zhangjiasong
 * @description: TODO
 * @date 2023/11/1 14:04
 */
@Component
public class UseUtil {

    @Value("${qinglian.API_KEY:A2fGsc1tQi69ShMcdWHzgwG7}")
    public String API_KEY;
    @Value("${qinglian.SECRET_KEY:Gh8vIPXn2uhL2T7ujUeughMibMrZaxeG}")
    public String SECRET_KEY;
    static final OkHttpClient HTTP_CLIENT = new OkHttpClient().newBuilder().build();

    public TreeMap<String, Object> useOcr(List<String> imgurl) throws IOException {
        List<List<String>> wordlist = new ArrayList<>();
        for (String img : imgurl) {
            String string = accurateBasic(img);
            List<String> wordsList = JSON.parseObject(string).getJSONArray("words_result").stream().map(obj -> {
                com.alibaba.fastjson.JSONObject jsonObject = (com.alibaba.fastjson.JSONObject) obj;
                return jsonObject.getString("words");
            }).collect(Collectors.toList());
            if (wordsList.size()==0) {
                throw exception(OCR_FILS_IS_NOT_EXISTS);
            }
            List<String> bodyList = wordsList.subList(2, wordsList.size());
            wordlist.add(bodyList);
        }
        //去除头尾数据
        List<String> resultlist = dataProcessingOne(wordlist);
        //拼接 完善数据
        TreeMap<String, Object> strings = dataProce(resultlist);
        //药方数据处理
        String string = (String) strings.get("dispose");
        String tentativeDiagnosis = (String) strings.get("tentative_diagnosis");
        if (StringUtil.isNotBlank(tentativeDiagnosis)) {
            String[] tentativeDiagnosisParts = Pattern.compile("\\d+\\.(?!\\d)").split(tentativeDiagnosis);
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 1; i < tentativeDiagnosisParts.length; i++) {
                stringBuilder.append(tentativeDiagnosisParts[i]);
                stringBuilder.append(",");
            }
            // 如果列表不为空，删除最后一个逗号
            if (tentativeDiagnosisParts.length > 0) {
                stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            }
            strings.put("tentative_diagnosis",stringBuilder.toString());
        }
        if (StringUtil.isNotBlank(string)) {
            String[] parts = Pattern.compile("\\d+\\.(?!\\d)").split(string);
            //处方处理 存入map
            List<Map<String, String>> reeultList = new ArrayList<>();
            for (int i = 1; i < parts.length; i++) {
                if (i==parts.length-1) {
                    String regex = "([^0-9]+)(\\d+克)";
                    Matcher matcher = Pattern.compile(regex).matcher(parts[i]);
                    while (matcher.find()) {
                        Map<String, String> clMap = new HashMap<>();
                        //药名
                        clMap.put("name",matcher.group(1));
                        //用量
                        clMap.put("message",matcher.group(2));
                        reeultList.add(clMap);
                    }
                    break;
                }
                Map<String, String> clMap = new HashMap<>();
                String[] split =parts[i].replace("，", ",").split(",",2);
                clMap.put("zname",split[0]);
                clMap.put("message",split[1]);
                reeultList.add(clMap);
            }
            strings.put("dispose",reeultList);
        }

        return strings;
    }


    /**
     * 拼接 完善数据
     * @param bodyList
     * @return
     */
    public TreeMap<String, Object> dataProce(List<String> bodyList) {
        TreeMap<String, Object> resultList = new TreeMap<>();
        String attern = "主诉：(.*?)|现病史：(.*?)|既往史：(.*?)|流行病学史：(.*?)|体格检查：(.*?)|初步诊断：(.*?)|辅助检查：(.*?)|.*\\d+付|处理：(.*?)$";
        Pattern pattern = Pattern.compile(attern);

        Map<String, String> map = new HashMap<>();
        for (OcrEnum ocrEnum : OcrEnum.values()) {
            map.put(ocrEnum.getIndex(), ocrEnum.getValue());
        }

        String pinjie = "";
        for (int i = 0; i < bodyList.size(); i++) {
            //Matcher pipei = pipei(bodyList.get(i));
            Matcher pipei = pattern.matcher(bodyList.get(i));
            if (StringUtil.isBlank(pinjie) && pipei.find() == false) {
                // 主诉上面数据不添加
                continue;
            }

            if (pipei.find() == true && StringUtil.isNotBlank(pinjie)) {
                //匹配到下个字段 清空数据
                String[] split = pinjie.split("：", 2);
                String mapvalue = map.get(split[0]);
                if (StringUtils.isNotBlank(mapvalue)) {
                    resultList.put(mapvalue,split[1]);
                }

                pinjie = "";
            }
            pinjie += bodyList.get(i);
        }

        return resultList;
    }

    /**
     * 数据处理  去除头尾数据
     *
     * @param bodyLists
     * @return
     */
    public List<String> dataProcessingOne(List<List<String>> bodyLists) {
        HashMap<String, List<String>> map = new HashMap<>();
        for (List<String> bodyList : bodyLists) {
            int fistindex = -1;
            for (int i = 0; i < bodyList.size(); i++) {
                if (bodyList.get(i).contains("就诊科室：")) {
                    fistindex = i + 1;
                    break;
                }
            }

            if (fistindex > 0) {
                bodyList.subList(0, fistindex).clear();
            }
            List<String> strings = bodyList.subList(bodyList.size() - 3, bodyList.size());
            Pattern pattern = Pattern.compile("第(\\d+)页");
            for (String string : strings) {
                Matcher matcher = pattern.matcher(string);
                if (matcher.find()) {
                    String number = matcher.group(1);
                    //System.out.println("匹配到的数字是：" + number);
                    strings.clear();
                    map.put(number, bodyList);
                    break;
                }
            }

        }

        List<String> collect = map.entrySet().stream()
                .map(Map.Entry::getValue)
                .flatMap(List::stream)
                .collect(Collectors.toList());

        return collect;
    }





    /**
     * 药量数据处理  根据Rp获取药方 ========== 已弃用
     *
     * @param bodyList
     * @return
     */
    public List<String> dataProcessing(List<String> bodyList) {
        List<String> resultList = new ArrayList<>();
        AtomicInteger index = new AtomicInteger(-1);
        bodyList.stream().filter(s -> {
                    //每比对一个元素，数值加1
                    index.getAndIncrement();
                    return s.toLowerCase().contains("rp".toLowerCase());
                })
                .findFirst();
        String message = "";
        for (int i = index.intValue(); i < bodyList.size(); i--) {
            if (message.contains("诊断")) {
                break;
            }
            if (StringUtils.isNotBlank(message)) {
                message = bodyList.get(i - 1) + "," + message;
                continue;
            }
            message = bodyList.get(i - 1) + message;
        }
        resultList.add(message);
        Pattern compile = Pattern.compile("[^空字符\\n](\\d+克)");

        for (int i = index.intValue() + 1; i < bodyList.size(); i++) {
            if (bodyList.get(i) == null || bodyList.get(i).toLowerCase().contains("rp".toLowerCase())) { // 如果项为空字符串，则跳过
                continue;
            }
            Matcher matcher2 = compile.matcher(bodyList.get(i));
            if (matcher2.find(1)) {
                resultList.add(bodyList.get(i).replaceFirst("(\\d+)", " $1"));
            } else {
                if (i == bodyList.size() - 1) {
                    continue;
                }
                String string = bodyList.get(i) + " " + bodyList.get(i + 1);
                bodyList.set(i + 1, null);
                if (compile.matcher(string).find(1)) {
                    resultList.add(string);
                }
            }
        }
        return resultList;
    }


    /**
     * 从用户的AK，SK生成鉴权签名（Access Token）
     *
     * @return 鉴权签名（Access Token）
     * @throws IOException IO异常
     */
    public String getAccessToken() throws IOException {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "grant_type=client_credentials&client_id=" + API_KEY + "&client_secret=" + SECRET_KEY);
        Request request = new Request.Builder().url("https://aip.baidubce.com/oauth/2.0/token").method("POST", body).addHeader("Content-Type", "application/x-www-form-urlencoded").build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        return new JSONObject(response.body().string()).getString("access_token");
    }

    public String accurateBasic(String imageUrl2) throws IOException {
        // 请求url
        String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic";
        imageUrl2 = URLEncoder.encode(imageUrl2);
        try {
            // 本地文件路径
//            String filePath = imageUrl2;
//            byte[] imgbodyList = FileUtil.readFileByBytes(filePath);
//            String imgStr = Base64Util.encode(imgbodyList);
//            String imgParam = URLEncoder.encode(imgStr, "UTF-8");

            String param = "image=" + imageUrl2 + "&detect_direction=true";

            // 注意这里仅为了简化编码每一次请求都去获取access_token，线上环境access_token有过期时间， 客户端可自行缓存，过期后重新获取。
            String accessToken = getAccessToken();
            String result = HttpUtil.post(url, accessToken, param);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

}
